package com.org.cloud.lg.custom;
import com.org.cloud.lg.constants.SecurityConstants;
import com.org.cloud.lg.utils.Checker;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/*
 * @Author LG
 * @Description   资源认证管理-用来认证资源是否允许访问动态验证
 * @Date 15:59 2019/4/30
 * @Param
 * @return
 **/
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {

	@Override
	public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		//configAttributes:当前访问url 代表的标识  authorities：认证用户所拥有的权限标识
		boolean notRequired=configAttributes.size()==1&&configAttributes.contains(new SecurityConfig(SecurityConstants.NOT_REQUIRED_HAVE_PERM));
		if(notRequired){
			return ;
		}
		//Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
		Collection<? extends GrantedAuthority> authorities =authentication.getAuthorities();
		if (Checker.BeEmpty(authorities)) {
			// 抛出该异常则会进入 CustomAccessDeniedHandler
			throw new AccessDeniedException("User has not Permission");
		}
		Set<String> authSets = authorities.stream().map(auth -> auth.getAuthority()).collect(Collectors.toSet());
		Set<String> needAuthSets = configAttributes.stream().map(auth -> auth.getAttribute()).collect(Collectors.toSet());
		boolean beMatch = authSets.containsAll(needAuthSets);
		if (!beMatch) {
			//抛出该异常会执行自定义 CustomAccessDeniedHandler
			throw new AccessDeniedException("用户权限不足,请联系管理员");
		}
		return;
	}

	@Override
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

	
}
